/*
* Copyright(C) 2009, kesalin All rights reserved.
* 
* File name : UWevControl.h
* Brief     : WevControl.
* Version   : 1.0
* Author    : kesalin@gmail.com
* Date      : 2009-6-5
*/

#pragma once

#include "UHostEventSink.h"
#include "UHostUIHandler.h"

namespace LuoUtils {

using ATL::CAxWindow;
using ATL::CWindow;
using ATL::CComPtr;

using LuoUtils::UHostUIHandler;
using LuoUtils::UHostEventSink;

// UWebControl
class UWebControl : public LuoUtils::UHostEventTarget {

	CAxWindow m_WebControl;

	CComPtr<IWebBrowser2> m_WebBrowser;

	CComPtr<IHTMLDocument2> m_WebDocument;

	UHostUIHandler m_UIHandler;

	UHostEventSink* m_pEventSink;

	CStringW m_Title;

public:

	UWebControl() : m_pEventSink(0)
	{
	}

	~UWebControl()
	{
		SafeRelease();
	}

	static UWebControl* Create();

	CWindow& GetControl()
	{
		return m_WebControl;
	}

	IWebBrowser2* GetWebBrowser()
	{
		return m_WebBrowser;
	}

	IHTMLDocument2* GetWebDocument()
	{
		return m_WebDocument;
	}

	LPCWSTR GetTitleText() const
	{
		return  m_Title;
	}

	void ReleaseWebDocument()
	{
		m_WebDocument.Release();
	}

	HRESULT Create(
		HWND hwnd,
		UINT id)
	{
		HWND hWebCtrl = m_WebControl.Create(
			hwnd,
			0,
			_T(""),
			WS_CHILD,
			0,
			id);
		if (hWebCtrl == 0) {
			return E_OUTOFMEMORY;
		}

		HRESULT hRslt = m_WebControl.CreateControl(
			L"Shell.Explorer.2");
		if (FAILED(hRslt)) {
			return hRslt;
		}

		hRslt = m_WebControl.SetExternalUIHandler(&m_UIHandler);
		if (FAILED(hRslt)) {
			return hRslt;
		}

		hRslt = m_WebControl.QueryControl(&m_WebBrowser);
		if (FAILED(hRslt)) {
			return hRslt;
		}

		hRslt = UHostEventSink::Create(&m_pEventSink, this);
		if (FAILED(hRslt)) {
			return hRslt;
		}

		hRslt = m_pEventSink->DoAdvise(m_WebBrowser);
		if (FAILED(hRslt)) {
			return hRslt;
		}

		{
			ATL::CComPtr<IAxWinAmbientDispatchEx> adex;
			m_WebControl.QueryHost(&adex);
			if (adex != 0) {
				adex->SetAmbientDispatch(&m_UIHandler);
			}
		}

		return S_OK;
	}

	HRESULT SetupDropTarget(IDropTarget* p)
	{
		if (p == 0) {
			m_WebBrowser->put_RegisterAsDropTarget(VARIANT_FALSE);
			return S_OK;
		}

		m_UIHandler.SetupDropTarget(p);
		m_WebBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);

		return S_OK;
	}

	HRESULT SetupExternal(IDispatch* p)
	{
		if (p == 0) {
			return E_INVALIDARG;
		}

		m_UIHandler.SetupExternal(p);

		return S_OK;
	}

	HRESULT SetupAmbientDLControl(DWORD flags)
	{
		m_UIHandler.SetupAmbientDLControl(flags);

		{
			ATL::CComPtr<IOleControl> oc;
			m_WebControl.QueryHost(&oc);
			if (oc != 0) {
				oc->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
			}
		}

		return S_OK;
	}

	bool PreTranslateMessage(MSG* pMsg)
	{
		HWND hwnd = m_WebControl;
		if (hwnd != 0 && pMsg != 0) {
			if ((pMsg->message < WM_KEYFIRST   || pMsg->message > WM_KEYLAST) &&
				(pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST)) {
				return false;
			}

			HWND hFocus = GetFocus();
			if (m_WebControl.IsChild(hFocus)) {
				bool done = SendMessage(hwnd, WM_FORWARDMSG, 0, (LPARAM)pMsg) != 0;
				if (done) {
					return true;
				}
			}
		}

		return false;
	}

public:

	virtual void STDCALL OnNavigateComplete()
	{
		if (m_WebDocument == 0) {
			CComPtr<IDispatch> disp;
			HRESULT hRslt = m_WebBrowser->get_Document(&disp);
			if (SUCCEEDED(hRslt)) {
				hRslt = disp.QueryInterface(&m_WebDocument);
				if (SUCCEEDED(hRslt)) {
					m_WebControl.ShowWindow(SW_NORMAL);
				}
			}
		}
	}

	virtual void STDCALL OnChangeTitle(LPCWSTR p)
	{
		m_Title = p;

#if 0
		{
			CStringA msg(p);
			ATLTRACE("OnChangeTitle: %s\n", (const char*)msg);
		}
#endif
	}

private:

	void SafeRelease()
	{
		if (m_pEventSink != 0) {
			m_pEventSink->DoUnadvise();
			m_pEventSink->Release();
			m_pEventSink = 0;
		}

		m_WebBrowser.Release();
	}

public:

	bool QueryCommandCopy()
	{
		if (m_WebDocument == 0) {
			return false;
		}

		ATL::CComBSTR copy(L"Copy");

		VARIANT_BOOL bOK;
		HRESULT hRslt = m_WebDocument->queryCommandEnabled(copy, &bOK);
		if (FAILED(hRslt)) {
			return false;
		}

		if (bOK != VARIANT_TRUE) {
			return false;
		}

		return true;
	}

	void ExecCommandCopy()
	{
		if (m_WebDocument == 0) {
			return;
		}

		ATL::CComBSTR copy(L"Copy");
		ATL::CComVariant vNull;
		VARIANT_BOOL bOK;
		HRESULT hRslt = m_WebDocument->execCommand(
			copy,
			VARIANT_FALSE,
			vNull,
			&bOK);
	}

}; // UWebControl

} // namespace LuoUtils

